/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.entity.accessor.entity;

import com.inspur.edp.cef.entity.accessor.base.IAccessor;
import com.inspur.edp.cef.entity.accessor.entity.IChildAccessor;
import com.inspur.edp.cef.entity.accessor.entity.IEntityAccessor;
import com.inspur.edp.cef.entity.accessor.entity.RootEntityAccessor;
import com.inspur.edp.cef.entity.dependenceTemp.DataValidator;
import com.inspur.edp.cef.entity.entity.ICefData;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.entity.entity.IEntityDataCollection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public abstract class AccessorCollection implements IEntityDataCollection
{
	//TODO: 生成的子类构造函数里加上collection属性, 这里就不需要public
	//protected IEntityAccessor Parent { get; private set; }
	private IEntityAccessor privateParent;
	public final IEntityAccessor getParent()
	{
		return privateParent;
	}
	public final void setParent(IEntityAccessor value)
	{
		privateParent = value;
	}

	public AccessorCollection(IEntityAccessor belongEntity)
	{
		setParent(belongEntity);
	}

	private java.util.LinkedHashMap<String, IEntityData> dict = new java.util.LinkedHashMap<String, IEntityData>();

//	public final java.util.Iterator<IEntityData> GetEnumerator()
//	{

//		{

//		}
//	}

//	private java.util.Iterator GetEnumerator()
//	{
//		return GetEnumerator();
//	}
	public int getCount()
	{
		return dict.size();
	}
	protected void beforeAdd(IEntityData item)
	{
	}

	private void fireItemAdded(IEntityData item)
	{
		if (getParent() == null)
		{
			return;
		}

		IAccessor tempVar = getParent().getRoot();

		RootEntityAccessor rootAccessor = (RootEntityAccessor)((tempVar instanceof RootEntityAccessor) ? tempVar : null);
		if (rootAccessor == null)
		{
			return;
		}
		rootAccessor.fireChildAdded((IChildAccessor)((item instanceof IChildAccessor) ? item : null), this);
	}

	public final void innerAdd(IEntityData item)
	{
		if (item instanceof IChildAccessor)
		{
			((IChildAccessor)item).setParent(getParent());
		}
		dict.put(item.getID(), item);
	}

	public final  void innerDelete(String id)
	{
		dict.remove(id);
	}

	protected Collection<IEntityData> innerGetAll() {
		return dict.values();
	}

	protected void beforeClear()
	{
	}

	public final void clear()
	{
		beforeClear();
		List<IEntityData> datas = new ArrayList<>(dict.values());
		for (IEntityData data : datas){
			beforeRemove(data);
		}
		dict.clear();
		for (IEntityData data : datas){
			fireItemRemoved(data);
		}
	}

	public final boolean contains(IEntityData item)
	{
		return dict.containsKey(item.getID());
	}

	protected void beforeRemove(IEntityData item)
	{
	}

	public final boolean remove(IEntityData item)
	{
		DataValidator.checkForNullReference(item, "item");
		return remove(item.getID());
	}

	private void fireItemRemoved(IEntityData item)
	{
		if (getParent() == null)
		{
			return;
		}
		IAccessor tempVar = getParent().getRoot();

		RootEntityAccessor rootAccessor = (RootEntityAccessor)((tempVar instanceof RootEntityAccessor) ? tempVar : null);
		if (rootAccessor == null)
		{
			return;
		}
		rootAccessor.fireChildRemoved((IChildAccessor)((item instanceof IChildAccessor) ? item : null), this);
	}

	 public boolean getIsReadOnly()
	 {return false;}

		public IEntityData getItem(String id)
		{
			return dict.get(id);
		}
//		public void setItem(String id, IEntityData value)
//		{dict.put(id,value);}



	public final IEntityData tryGet(String id)
	{
		IEntityData result = dict.get(id);
		return result;
	}

	public abstract IChildAccessor createInstance();

	public final void copyTo(IEntityData[] array, int arrayIndex)
	{
		int index=0;
		for (Map.Entry<String, IEntityData> entry: dict.entrySet())
		{
			array[index]=entry.getValue();
			index++;
		}
	}

	public final boolean remove(String id)
	{
		DataValidator.checkForNullReference(id, "id");

		IEntityData item = dict.get(id);
		beforeRemove(item);

		 dict.remove(item.getID());
		fireItemRemoved(item);
		return true;
	}

	public final boolean contains(String id)
	{
		DataValidator.checkForNullReference(id, "id");
		return dict.containsKey(id);
	}

	protected abstract AccessorCollection createNewObject();

	public final AccessorCollection copy(IEntityAccessor parent)
	{
		AccessorCollection newCollection = (AccessorCollection)createNewObject();
		newCollection.setParent( parent);
		copyDict(newCollection,parent);
		return newCollection;
	}

	private void copyDict(AccessorCollection newCollection,IEntityAccessor parent)
	{
		for (Map.Entry<String, IEntityData> enriy: dict.entrySet())
		{
			IEntityData newItem = (IEntityData)enriy.getValue().copy();
			if(newItem instanceof  IChildAccessor) {
				IChildAccessor newChild =(IChildAccessor) newItem;
				newChild.setParent(parent);
			}
			newCollection.dict.put(enriy.getKey(), newItem);
		}
	}

	//region ICollection接口需要但未实现的方法

	@Override
	public void setItem(String s, IEntityData iEntityData) {
throw new UnsupportedOperationException();
	}

	@Override
	public int size() {
		return dict.size();

	}

	@Override
	public boolean isEmpty() {
		return dict.isEmpty();

	}

	@Override
	public boolean contains(Object o) {
		throw new UnsupportedOperationException();

	}

	@Override
	public Iterator<IEntityData> iterator() {
		return new Iterator<IEntityData>() {
			private Iterator<Map.Entry<String, IEntityData>> index = dict.entrySet().iterator();
			@Override
			public boolean hasNext() {
				return index.hasNext();
			}

			@Override
			public IEntityData next() {
				return index.next().getValue();
			}
		};
	}

	@Override
	public Object[] toArray() {
		return dict.values().toArray();

	}

	@Override
	public <T> T[] toArray(T[] a) {
		throw new UnsupportedOperationException();

	}

	@Override
	public boolean add(IEntityData item) {
		if (item instanceof IChildAccessor)
		{
			((IChildAccessor)item).setParent(getParent());
		}
		beforeAdd(item);
		dict.put(item.getID(), item);
		fireItemAdded(item);
		return true;
	}

	@Override
	public boolean remove(Object o) {
		dict.remove(o);
		return true;
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		throw new UnsupportedOperationException();

	}

	@Override
	public boolean addAll(Collection<? extends IEntityData> c) {
		Objects.requireNonNull(c);

		for (IEntityData d : c) {
			add(d);
		}
		return true;
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		throw new UnsupportedOperationException();
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		throw new UnsupportedOperationException();
	}
	//endregion
}
